package com.yn.pet.controller.pc.biz;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yn.common.core.redis.RedisCache;
import com.yn.common.utils.DateUtils;
import com.yn.common.utils.StringUtils;
import com.yn.common.utils.bean.BeanUtils;
import com.yn.pet.bus.entity.DeviceInfo;
import com.yn.pet.bus.entity.LocationRealtime;
import com.yn.pet.bus.enums.DeviceStatusEnum;
import com.yn.pet.controller.pc.request.CollectionQueryRequest;
import com.yn.pet.controller.pc.request.PetRequest;
import com.yn.pet.controller.pc.response.CollectionQueryResponse;
import com.yn.pet.controller.pc.response.ImmediateLocationResponse;
import com.yn.pet.controller.pc.response.PetResponse;
import com.yn.pet.controller.pc.response.page.CollectionPageResponse;
import com.yn.pet.entity.*;
import com.yn.pet.enums.GenderEnum;
import com.yn.pet.enums.PetTypeEnum;
import com.yn.pet.service.*;
import com.yn.pet.util.AppTokenUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Slf4j
public class PetBizService {

    private final PetService petService;
    private final AppUserService appUserService;
    private final DeviceInfoService deviceInfoService;
    private final DeviceGroupService deviceGroupService;

    private final RedisCache redisCache;

    private final LocationRealtimeService locationRealtimeService;

    private static final AtomicInteger locationCounter = new AtomicInteger(0);

    private final String KEY_PREFIX = "deviceStatus:";
    public IPage<PetResponse> pageList(PetRequest request) {
        Integer currentPage = request.getCurrentPage();
        Integer pageSize = request.getPageSize();
        if (currentPage == null) {
            currentPage = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        }
        Long userId = null;
        if (StringUtils.isNotBlank(request.getPhone())) {
            AppUser appUser = appUserService.getByPhone(request.getPhone());
            if (appUser != null) {
                userId = appUser.getAppUserId();
            }
        }
        LambdaQueryWrapper<Pet> queryWrapper = new LambdaQueryWrapper<Pet>()
                .eq(!Objects.isNull(userId), Pet::getUserId, userId)
                .ge(!Objects.isNull(request.getBindTimeStart()), Pet::getBindTime, request.getBindTimeStart())
                .le(!Objects.isNull(request.getBindTimeEnd()), Pet::getBindTime, request.getBindTimeEnd())
                .eq(!Objects.isNull(request.getPetType()), Pet::getPetType, request.getPetType())
                .eq(!Objects.isNull(request.getGender()), Pet::getGender, request.getGender())
                .eq(StringUtils.isNotBlank(request.getColor()), Pet::getColor, request.getColor())
                .like(StringUtils.isNotBlank(request.getPetName()), Pet::getPetName, request.getPetName())
                .isNull(Pet::getUnBindTime)
                .eq(Pet::getDataStatus, 1);
        Page<Pet> page = petService.page(new Page<>(currentPage, pageSize), queryWrapper);
        return page.convert(pet -> {
            PetResponse petResponse = new PetResponse();
            BeanUtils.copyBeanProp(petResponse, pet);

            AppUser appUser = appUserService.getById(pet.getUserId());
            if (appUser != null) {
                petResponse.setPhone(appUser.getPhone());
                petResponse.setNickName(appUser.getNickname());
            }
            DeviceInfo deviceInfo = deviceInfoService.getById(pet.getDeviceId());
            if (deviceInfo != null) {
                petResponse.setImei(deviceInfo.getImei());
            }

            Integer petType = pet.getPetType();
            String name = PetTypeEnum.getNameByCode(petType);
            petResponse.setPetTypeName(name);

            String genderName = GenderEnum.getNameByCodeAndPetType(pet.getGender(), petType);
            petResponse.setGenderName(genderName);
            return petResponse;
        });
    }

    /**
     * 用户绑定设备
     * @param imeis 绑定请求对象
     * @return
     */
    @Transactional
    public void bindDevice(String imeis, Long groupId) {
        String[] imeiArr = imeis.split(",");
        //获取当前用户信息
        AppUser user = AppTokenUtil.getAppUser();
        if(user==null){
            throw new RuntimeException("用户信息不存在");
        }
        Long userId = user.getAppUserId();
        //检查该设备是否存在，得到设备id
        for (String imei : imeiArr) {
            DeviceInfo deviceInfo = deviceInfoService.getByImei(imei);
            if(deviceInfo==null){
                throw new RuntimeException("设备信息不存在");
            }
            //判断设备状态改变时间是否有值，如果没有，则设置
            if(deviceInfo.getStatusChangeTime()==null){

                LambdaUpdateWrapper<DeviceInfo> wrapper = Wrappers.lambdaUpdate();

                wrapper.eq(DeviceInfo::getDeviceId, deviceInfo.getDeviceId());
                wrapper.set(DeviceInfo::getStatusChangeTime,new Date());
                deviceInfoService.update(wrapper);
            }
            //判断当前用户是否绑定过当前设备
            LambdaQueryWrapper<Pet> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.eq(Pet::getDeviceId, deviceInfo.getDeviceId())
                    .eq(Pet::getUserId, userId)
                    .eq(Pet::getDataStatus, 1)
                    .isNull(Pet::getUnBindTime);
            Pet pet = petService.getOne(lambdaQuery);
            if(pet!=null){
                throw new RuntimeException("当前用户已绑定此设备");
            }
            Pet transform = new Pet();
            transform.setDeviceId(deviceInfo.getDeviceId());
            //关联用户id，创建人，更新人
            transform.setUserId(userId);
            transform.setCreateBy(user.getPhone());
            transform.setUpdateBy(user.getPhone());
            if(user.getNickname()!=null){
                transform.setCreateBy(user.getNickname());
                transform.setUpdateBy(user.getNickname());
            }
            transform.setGroupId(groupId);
            transform.setBindTime(LocalDateTime.now());
            petService.save(transform);
            //给位置同步表添加天安门的固定座标(最后三位坐标随机)
            String randomLongitudeStr =generateThreeDigitId();
            String longitude = 116.397+randomLongitudeStr;
            String randomLatitudeStr =generateThreeDigitId();
            String latitude = 39.90+randomLatitudeStr;
            LocationRealtime locationRealtime = new LocationRealtime();
            locationRealtime.setDeviceId(deviceInfo.getDeviceId());
            locationRealtime.setLongitude(Double.valueOf(longitude));
            locationRealtime.setLatitude(Double.valueOf(latitude));
            locationRealtime.setDataStatus(2);
            locationRealtimeService.save(locationRealtime);
        }
    }

    /**
     * 解绑设备信息
     * @param deviceId 设备ID
     * @return
     */
    public void unBindDevice(Long deviceId) {
        //当前登录人信息
        //获取当前用户信息
        AppUser user = AppTokenUtil.getAppUser();
        if(user==null){
            throw new RuntimeException("用户信息不存在");
        }
        Long userId=user.getAppUserId();
        Pet pet= petService.getByDeviceIdAndUserId(deviceId,userId);
        if(pet==null){
            throw new RuntimeException("当前设备未绑定");
        }
        pet.setUnBindTime(new Date());
        //删除该数据
        LambdaUpdateWrapper<Pet> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(Pet::getPetId,pet.getPetId()).set(Pet::getDataStatus,0).set(Pet::getUnBindTime,new Date());
        petService.update(wrapper);
    }

    /**
     * 绑定设备到分组
     * @param deviceId 设备ID
     * @param groupId 分组ID
     * @return
     */
    public void transferDevice(Long deviceId, Long groupId) {
        //当前登录人信息
        //获取当前用户信息
        AppUser user = AppTokenUtil.getAppUser();
        if(user==null){
            throw new RuntimeException("用户信息不存在");
        }
        Long userId = user.getAppUserId();
        Pet pet = petService.getByDeviceIdAndUserId(deviceId, userId);
        if(pet==null){
            throw new RuntimeException("设备不存在");
        }

        LambdaUpdateWrapper<Pet> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(Pet::getDeviceId, deviceId)
                .eq(Pet::getUserId, userId)
                .eq(Pet::getDataStatus, 1)
                .set(Pet::getGroupId, groupId);
        petService.update(wrapper);
    }

    /**
     * 获取用户绑定设备列表
     * @return ImmediateLocationResponse
     */
    public List<ImmediateLocationResponse> deviceInfoList() {
        //当前登录人信息
        AppUser user = AppTokenUtil.getAppUser();
        if(user==null){
            throw new RuntimeException("用户信息不存在");
        }
        Long userId = user.getAppUserId();
        log.info("用户ID:{}",userId);

        List<Pet> pets = petService.listByUserId(userId);
        if(CollectionUtils.isEmpty(pets)){
            return Collections.emptyList();
        }
        //通过stream流获取设备id集合
        Set<Long> deviceIdSet = pets.stream().map(Pet::getDeviceId).collect(Collectors.toSet());
        if(CollectionUtils.isEmpty(deviceIdSet)){
            return Collections.emptyList();
        }
        //获得map
        Map<Long, Pet> petMaps = pets.stream().collect(Collectors.toMap(Pet::getDeviceId, pet -> pet));
        //查询设备信息
        LambdaQueryWrapper<DeviceInfo> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.in(DeviceInfo::getDeviceId, deviceIdSet);
        List<DeviceInfo> deviceInfoList = deviceInfoService.list(lambdaQuery);
        if(CollectionUtils.isEmpty(deviceInfoList)){
            return Collections.emptyList();
        }

        ArrayList<ImmediateLocationResponse> responses = new ArrayList<>(pets.size());
        for (DeviceInfo info : deviceInfoList) {
            //离线设备不统计
            ImmediateLocationResponse response = new ImmediateLocationResponse();
            Integer petType = petMaps.get(info.getDeviceId()).getPetType();
            response.setPetType(petType);
            response.setPetTypeStr(PetTypeEnum.getByCode(petType).getName());
            response.setDeviceId(info.getDeviceId());
           if(StringUtils.isEmpty(info.getDeviceName())){
               response.setDeviceName(info.getImei());
           }else{
               response.setDeviceName(info.getDeviceName());
           }
            response.setImei(info.getImei());
           response.setDeviceStatus(info.getDeviceStatus());
           response.setDeviceStatusStr(DeviceStatusEnum.getByCode(info.getDeviceStatus()).getName());
           //获取定位表的最新一条数据
            LocationRealtime location = locationRealtimeService.getLatestLocationByDeviceId(info.getDeviceId());
            if(location == null){
                throw new RuntimeException("设备没有定位信息");
            }
            response.setLocationId(location.getLocationId());
            response.setLongitude(location.getLongitude());
            response.setLatitude(location.getLatitude());
            response.setDetailedLocation(location.getDetailedLocation());

            responses.add(response);

        }

        return responses;
    }

    /**
     * 是否收藏设备（0 否 1是）
     * @param deviceId 设备id
     * @param isCollection 是否收藏 0 否 1是
     * @return 无
     */
    public void collection(Long deviceId, Integer isCollection) {
        //当前登录人信息
        AppUser user = AppTokenUtil.getAppUser();
        if(user==null){
            throw new RuntimeException("用户信息不存在");
        }
        Long userId = user.getAppUserId();
        Pet pet = petService.getByDeviceIdAndUserId(deviceId, userId);
        if(pet==null){
            throw new RuntimeException("设备信息不存在");
        }
        if (Objects.equals(pet.getIsCollection(), isCollection)){
            throw new RuntimeException("请勿重复操作");
        }
        //petService.updateById(pet);
        LambdaUpdateWrapper<Pet> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(Pet::getPetId, pet.getPetId())
                .set(Pet::getIsCollection, isCollection)
                .set(Pet::getUpdateTime, new Date());
        petService.update(wrapper);
    }
    public CollectionPageResponse pageCollectionList(CollectionQueryRequest request) {

        Integer currentPage = request.getCurrentPage();
        Integer pageSize = request.getPageSize();
        if (currentPage == null) {
            currentPage = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        }
        //获取用户信息
        AppUser appUser = AppTokenUtil.getAppUser();
        if(appUser==null){
            throw new RuntimeException("当前用户未登录");
        }
        Long userId = appUser.getAppUserId();
        String avatar = appUser.getAvatar();
        //构建查询条件
        List<Pet> pets = petService.listByUserId(userId);
        //筛选出已收藏的
        pets=pets.stream().filter(pet -> pet.getIsCollection()==1).collect(Collectors.toList());
        CollectionPageResponse pageResponse = new CollectionPageResponse();
        List<CollectionQueryResponse> records=new ArrayList<>();
        if(CollectionUtils.isEmpty(pets)){
            log.info("用户没有绑定设备");
            pageResponse.setRecords(records);
            pageResponse.setOnlineCount(0);
            pageResponse.setStaticCount(0);
            pageResponse.setOfflineCount(0);
            pageResponse.setTotal(0);
            pageResponse.setPages(0);
            pageResponse.setCurrent(currentPage);
            pageResponse.setOptimizeCountSql(false);
            return pageResponse;
        }
        //获取用户绑定的设备id
        Set<Long> deviceIds = pets.stream().map(Pet::getDeviceId).collect(Collectors.toSet());
        LambdaQueryWrapper<DeviceInfo> lambdaQuery = Wrappers.lambdaQuery();
        /*if(request.getDeviceStatus()!=null){
            lambdaQuery.eq(DeviceInfo::getDeviceStatus, request.getDeviceStatus());
        }*/
        if(StringUtils.isNotEmpty(request.getImei())){
            lambdaQuery.like(DeviceInfo::getImei, request.getImei());
        }
            lambdaQuery.in(DeviceInfo::getDeviceId, deviceIds);
            List<DeviceInfo> deviceInfos = deviceInfoService.list(lambdaQuery);
            //分别得到设备的总个数，运动个数，静止个数，离线个数
            pageResponse.setDeviceTotalCount(deviceInfos.size());
            //运动个数
            pageResponse.setOnlineCount((int)deviceInfos.stream().filter(deviceInfo -> deviceInfo.getDeviceStatus().equals(DeviceStatusEnum.MOVING.getCode())).count());
            //静止个数
            pageResponse.setStaticCount((int)deviceInfos.stream().filter(deviceInfo -> deviceInfo.getDeviceStatus().equals(DeviceStatusEnum.STATIC.getCode())).count());
            //离线个数
            pageResponse.setOfflineCount((int)deviceInfos.stream().filter(deviceInfo -> deviceInfo.getDeviceStatus().equals(DeviceStatusEnum.OFFLINE.getCode())).count());

            //过滤得到符合筛选条件的设备集合
            if (request.getDeviceStatus()!=null){
               deviceInfos=deviceInfos.stream().filter(deviceInfo -> deviceInfo.getDeviceStatus().equals(request.getDeviceStatus())).collect(Collectors.toList());
            }
            if(CollectionUtils.isEmpty(deviceInfos)){
                log.info("根据条件筛选得到的设备列表：{}", deviceInfos);
                pageResponse.setRecords(records);
                pageResponse.setOnlineCount(0);
                pageResponse.setStaticCount(0);
                pageResponse.setOfflineCount(0);
                pageResponse.setDeviceTotalCount(0);
                pageResponse.setTotal(0);
                pageResponse.setPages(0);
                pageResponse.setCurrent(currentPage);
                pageResponse.setOptimizeCountSql(false);
                return pageResponse;
            }
            deviceIds = deviceInfos.stream().map(DeviceInfo::getDeviceId).collect(Collectors.toSet());

            //将设备信息转为map<deviceId,deviceInfo>
            Map<Long, DeviceInfo> deviceInfoMap = deviceInfos.stream().collect(Collectors.toMap(DeviceInfo::getDeviceId, deviceInfo -> deviceInfo));

        LambdaQueryWrapper<Pet> petQuery = Wrappers.lambdaQuery();
        petQuery.in(Pet::getDeviceId, deviceIds);
        Page<Pet> page = petService.page(new Page<>(currentPage, pageSize), petQuery);
        page.getRecords().forEach(pet -> {
            CollectionQueryResponse response = new CollectionQueryResponse();
            response.setDeviceId(pet.getDeviceId());
            response.setAvatar(avatar);
            //根据设备id查询设备信息
            DeviceInfo deviceInfo = deviceInfoMap.get(pet.getDeviceId());
            response.setDeviceName(deviceInfo.getDeviceName());
            String imei = deviceInfo.getImei();
            response.setImei(imei);
            //设备状态
            response.setDeviceStatus(deviceInfo.getDeviceStatus());
            response.setDeviceStatusName(DeviceStatusEnum.getByCode(deviceInfo.getDeviceStatus()).getName());
            //设备状态持续时间
            response.setContinueTime(DateUtils.timeDistance(new Date(), deviceInfo.getStatusChangeTime()));
            LocationRealtime one = locationRealtimeService.getLatestLocationByDeviceId(pet.getDeviceId());
            if(one==null){
                response.setMileage(0.0);
            }else{
                response.setMileage(one.getMileage());
            }
           records.add(response);
        });
        pageResponse.setRecords(records);
        pageResponse.setTotal(page.getTotal());
        pageResponse.setSize(page.getSize());
        pageResponse.setPages(page.getPages());
        pageResponse.setCurrent(page.getCurrent());
        pageResponse.setOptimizeCountSql(page.optimizeCountSql());
        log.info("设备列表查询结果：{}", pageResponse);
        return pageResponse;
    }
    // 生成三位随机数字（001-999）的工具方法
    public static String generateThreeDigitId() {
        int current = locationCounter.getAndIncrement();
        if (current >= 999) {
            locationCounter.compareAndSet(current + 1, 1);
            current = locationCounter.getAndIncrement();
        }
        return String.format("%03d", current);
    }

    public void batchCancelCollection(Set<Long> deviceIds) {
        //当前登录人信息
        AppUser user = AppTokenUtil.getAppUser();
        if(user==null){
            throw new RuntimeException("用户信息不存在");
        }
        Long userId = user.getAppUserId();
        //LambdaUpdateWrapper<Pet> wrapper = Wrappers.lambdaUpdate();
        List<Pet> pets = petService.getByDeviceIdsAndUserId(deviceIds, userId);
        if(CollectionUtils.isEmpty(pets)){
            throw new RuntimeException("设备信息不存在");
        }
        /*pets.forEach(pet -> {
            pet.setIsCollection(0);
        });
        petService.updateBatchById(pets);*/
        pets.forEach(pet -> {
            LambdaUpdateWrapper<Pet> wrapper = Wrappers.lambdaUpdate();
            wrapper.eq(Pet::getPetId, pet.getPetId())
                    .set(Pet::getIsCollection, 0)
                    .set(Pet::getUpdateTime, new Date());
            petService.update(wrapper);
        });
    }
}
